package examples;
import cern.colt.list.tdouble.DoubleArrayList;
import cern.colt.list.tint.IntArrayList;
import com.jom.DoubleMatrixND;
import com.jom.OptimizationProblem;

public class OptimizationControllers 
{
	public static void main(String[] args)
	{
		double distancia[][] = new double [7][7];
		distancia[0] = new double[] {  0, 405, 250, 375, 340, 165, 410};
		distancia[1] = new double[] {405,   0, 155, 245, 215, 240, 375};
		distancia[2] = new double[] {250, 155,   0, 400, 370, 395, 220};
		distancia[3] = new double[] {375, 245, 400,   0, 435, 485, 620};
		distancia[4] = new double[] {340, 215, 370, 435,   0, 455, 590};
		distancia[5] = new double[] {165, 240, 395, 485, 455,   0, 305};
		distancia[6] = new double[] {410, 375, 220, 620, 590, 305,   0};
		
		/* Create the optimization problem object */
		OptimizationProblem op = new OptimizationProblem();
		op.setInputParameter( "delays", distancia );
		op.addDecisionVariable( "selected", true, new int[] {7,7}, 0, 1);
		op.setObjectiveFunction( "maximize", "sum( delays .* selected )" );
		
		for( int i = 0; i < 7; i++ )
			op.addConstraint( "sum( selected( all, " + i + " ) ) == 1" );
		
		op.solve("glpk");
		
		if (!op.solutionIsOptimal ())
			throw new RuntimeException ("An optimal solution was not found");
			
		IntArrayList selectedIndexList = new IntArrayList();
		DoubleMatrixND selected = op.getPrimalSolution( "selected" );
		selected.getPositiveValues( selectedIndexList, new DoubleArrayList() );
		System.out.println( "delays: " + op.getInputParameter( "delays" ) );
		System.out.println( "selected: " + selected.toString() );

		int numNodesOk[] = new int[ 7 ]; 
		
		for( int i = 0; i < 7; i++ )
			for( int j = 0; j < 7; j++ )
				if( 0 < distancia[i][j] && distancia[i][j] <= 350 )
					numNodesOk[i]++;
				
		int index[] = selectedIndexList.elements();
		int ld[] = new int[7];
		
		for( int i = 0; i < 7; i++ )
		{
			ld[ i ] = (int) op.parseExpression( "delays(" + index[ i ] + ")" ).evaluate().toValue();
			System.out.print( ld[i] + "(" + numNodesOk[i] + ")" + ", " );
		}
		
		System.out.println( "\nTotal cost obtained: " + op.getOptimalCost() );
		
		// Seleccionar controladores
		
		OptimizationProblem op1 = new OptimizationProblem();		
		op1.addDecisionVariable( "x", true, new int[] {1,1}, 1, 7);
		op1.addDecisionVariable( "y", true, new int[] {1,1}, 1, 7);
		op1.setInputParameter( "delays", distancia );
		op1.setObjectiveFunction( "minimize", "x" );
		op1.addConstraint( "x + y == 7" );
		op1.addConstraint( "x + 1 <= y" );
		//op1.addConstraint( "delays(x,y) <= 350" );
		
		op1.solve("glpk");
	  	
		if (!op1.solutionIsOptimal ()) throw new RuntimeException ("An optimal solution was not found");
		
		System.out.println("x: " + op1.getPrimalSolution("x"));
		System.out.println("Total cost obtained: " + op1.getOptimalCost());
		
		/*OptimizationProblem op1 = new OptimizationProblem();
		op1.setInputParameter( "d", d );
		op1.setInputParameter( "ld", ld, "row" );		
		op1.addDecisionVariable( "ld", true, new int[] {1,7}, 0, Double.MAX_VALUE);
		op1.setObjectiveFunction( "maximize", "sum( d .* c' )" );*/
		
		/* Create the optimization problem object */
		/*OptimizationProblem op = new OptimizationProblem();
		
		op.addDecisionVariable( "c", true, new int[] {1,7}, 0, 1);
		op.setInputParameter( "ld", new int[] {410,405,400,620,590,485,620}, "row" );
		
		op.setObjectiveFunction("minimize", "sum(c .* ld)");
		op.addConstraint( "sum(c .* ld) >= 1" );*/
		
		/* Call the solver to solve the problem */
	  	/*op1.solve("glpk");
	  	
		if (!op1.solutionIsOptimal ()) throw new RuntimeException ("An optimal solution was not found");
			
		System.out.println("ld: " + op1.getPrimalSolution("ld"));
		System.out.println("Total cost obtained: " + op1.getOptimalCost());*/
	}
}
